package com.fare.taluo.application.impl.system.auth;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.apache.commons.lang3.StringUtils;
import org.openkoala.auth.application.vo.ResourceVO;
import org.openkoala.koala.auth.core.domain.Resource;
import org.openkoala.koala.auth.core.domain.ResourceLineAssignment;
import org.openkoala.koala.auth.core.domain.ResourceType;
import org.openkoala.koala.auth.core.domain.ResourceTypeAssignment;
import org.openkoala.util.DateFormatUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.dayatang.domain.QuerySettings;
import com.dayatang.utils.DateUtils;
import com.fare.taluo.application.system.auth.MenusApplication;
import com.fare.taluo.base.ddd.application.BaseApplicationImpl;
@Transactional(value="transactionManager_security")
@Service("menusApplication")
public class MenusApplicationImpl extends BaseApplicationImpl implements MenusApplication {

	public ResourceVO saveMenu(ResourceVO menuVO) {
		menuVO.setAbolishDate(DateFormatUtils.format(new Date()));
		menuVO.setCreateDate(DateFormatUtils.format(new Date()));
		menuVO.setLevel("1");
		menuVO.setSerialNumber("0");
		menuVO.setSortOrder(0);
		Resource resource = new Resource();
		menuVO.vo2Domain(resource);
		resource.save();
		saveResourceTypeAssignment(menuVO, resource);
		menuVO.setId(resource.getId());
		return menuVO;
	}
	
	private void saveResourceTypeAssignment(ResourceVO vo, Resource resource) {
		ResourceTypeAssignment resourceTypeAssignment = new ResourceTypeAssignment();
		resourceTypeAssignment.setCreateDate(new Date());
		resourceTypeAssignment.setAbolishDate(DateUtils.MAX_DATE);
		resourceTypeAssignment.setResource(resource);
		resourceTypeAssignment.setResourceType(ResourceType.load(ResourceType.class, Long.valueOf(vo.getMenuType())));
		resourceTypeAssignment.save();
	}
	
	public ResourceVO saveAndAssignParent(ResourceVO menuVO, ResourceVO parent) {
		ResourceVO child = this.saveMenu(menuVO);
		this.assign(parent, child);
		return child;
	}
	
	public void assign(ResourceVO parentVO, ResourceVO childVO) {
		Resource parent = new Resource();
		parent.setId(Long.valueOf(parentVO.getId()));
		Resource child = Resource.load(Resource.class, childVO.getId());
		child.setLevel(String.valueOf(Integer.parseInt(parentVO.getLevel()) + 1));
		child.setId(Long.valueOf(childVO.getId()));
		parent.assignChild(child);
	}

	@Override
	public ResourceVO find(String code) {
		//koala的菜单中没有code一说，我们暂时以desc属性来做标识
		ResourceVO vo = null;
		Resource resource = null;
	    List<Resource> results = Resource.getRepository()
				.find(QuerySettings.create(Resource.class).eq("desc", code));
		if(results != null && !results.isEmpty()){
			resource = results.get(0);
			if(resource != null){
				vo = new ResourceVO();
				vo.domain2Vo(resource);
			}
		}
		return vo;
	}

	@Override
	public List<ResourceVO> findByRole(Long roleId) {
		List<ResourceVO> results = new ArrayList<ResourceVO>();
		//按角色ＩＤ查询结果
		String hql = "select a.resource from IdentityResourceAuthorization a where a.identity.id=? and a.resource.abolishDate>?";
		List<Resource> objs = super.queryKoalaChannel().queryResult(hql, new Object[]{roleId, new Date()});
		List<ResourceVO> temps = new ArrayList<ResourceVO>();
		ResourceVO vo = null;
		ResourceLineAssignment rl = null;
		for(Resource r : objs){
			vo = new ResourceVO();
			vo.domain2Vo(r);
			vo.setText(vo.getName()!=null ? vo.getName():vo.getText());
			rl = this.findResRelations(r.getId());
			if(rl != null && rl.getParent()!=null)
				vo.setParentId(rl.getParent().getId().toString());
			
			temps.add(vo);
		}
		//组成树结构
		for(ResourceVO v : temps){
			if(StringUtils.isEmpty(v.getParentId())){
				results.add(v);
				this.buildMenuTree(v, temps);
			}
		}
		return results;
	}
	
	private void buildMenuTree(ResourceVO parent, List<ResourceVO> temps){
		if(parent.getChildren()==null) parent.setChildren(new ArrayList<ResourceVO>()); 
		for(ResourceVO vo : temps){
			if(StringUtils.isNotEmpty(vo.getParentId()) && vo.getParentId().equals(parent.getId().toString())){
				parent.getChildren().add(vo);
			}
		}
	}

	public ResourceLineAssignment findResRelations(Long childId) {
		String hql = "from ResourceLineAssignment a where a.child.id=?";
		return super.queryKoalaChannel().querySingleResult(hql, new Object[]{childId});
	}
}
